package snooker.scoreboard;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import snooker.scoreboard.entity.Type;
import snooker.scoreboard.frame.Frame;
import snooker.scoreboard.frame.FrameScoreHistory;
import snooker.scoreboard.frame.Score;
import snooker.scoreboard.persistence.SnookerSharedPreferences;
import snooker.scoreboard.util.Utils;
import android.os.SystemClock;
import android.util.Log;

public class Match {

	private static final String LOG_TAG = "Match";
	
	public static final int PLAYER1 = 1;
	public static final int PLAYER2 = 2;
	
	private static Match match;
	
	private List<Frame> frames;
	private String player1Name;
	private String player2Name;
	private int player1FrameWins;
	private int player2FrameWins;
	private Frame activeFrame;
	private Date startDate;
	private String fileName;
	private SnookerSharedPreferences ssp;
	
	private Match() {
		init();
	}

	private void init() {
		Log.i(LOG_TAG, "init() {");
		ssp = SnookerSharedPreferences.getInstance();
		player1FrameWins = 0;
		player2FrameWins = 0;
		frames = new LinkedList<Frame>();
		activeFrame = null;
		player1Name = ssp.getPlayer1Name();
		player2Name = ssp.getPlayer2Name();
		Log.i(LOG_TAG, " player2Name=" + player2Name);
		fileName = ssp.getFileName();
		if (fileName == null) {
			startDate = new Date();
			ssp.saveFileName(getFileName());
		}
		int prevFrameId = -1;
		int activeFrameId = ssp.getActiveFrameId();
		Log.i(LOG_TAG, " activeFrameId=" + activeFrameId);
		int playerId = Match.PLAYER1;
		int breakId = 0;
		List<Score> frameScores = new LinkedList<Score>();
		Score scores[] = ssp.getScores();
		if (scores.length == 0) {
			activeFrame = new Frame();
			return;
		}
		for (Score fScore: scores) {
			Log.i(LOG_TAG, "new Frame() " + fScore.getFrameId());
			if (prevFrameId == -1) {
				prevFrameId = fScore.getFrameId();
			}
			if (prevFrameId != fScore.getFrameId()) {
				List<Score> f = frameScores;
//				Log.i(LOG_TAG, "new Frame() " + frames.size());
				Frame newFrame = new Frame(frames.size() + 1, breakId, playerId, 
						new FrameScoreHistory(f));
				frames.add(newFrame);
				if (newFrame.getPlayer1Score() > newFrame.getPlayer2Score()) {
					player1FrameWins++;
				} else if (newFrame.getPlayer2Score() > newFrame.getPlayer1Score()) {
					player2FrameWins++;
				}
				frameScores = new LinkedList<Score>();
				prevFrameId = fScore.getFrameId();
			}
			
			breakId = fScore.getBreakId();
			
			frameScores.add(fScore);
		}
		if (prevFrameId == activeFrameId) {
			activeFrame = new Frame(frames.size() + 1, Settings.getInstance().getMaxReds());
			activeFrame.getScoreHistory().setSave(false);
			for (Score fScore: frameScores) {
				ssp.saveActFrameId(activeFrame.getFrameId());
				activeFrame.selectPlayer(fScore.getPlayerId());
				activeFrame.getScoreHistory().setStartTime(SystemClock.elapsedRealtime() - fScore.getEventTime());
				if (Type.UnintededRed.equals(fScore.getType())) {
					activeFrame.unintendedRed(fScore.isLuckyShot());
				} else {
					activeFrame.setScore(fScore.getBall(), Type.Foul.equals(fScore.getType()), fScore.isLuckyShot());
				}
			}
			activeFrame.getScoreHistory().setSave(true);
		} else {
			List<Score> f = frameScores;
			Frame newFrame = new Frame(frames.size() + 1, breakId, playerId, 
					new FrameScoreHistory(f));
			frames.add(newFrame);
			if (newFrame.getPlayer1Score() > newFrame.getPlayer2Score()) {
				player1FrameWins++;
			} else if (newFrame.getPlayer2Score() > newFrame.getPlayer1Score()) {
				player2FrameWins++;
			}
			activeFrame = new Frame(frames.size() + 1, Settings.getInstance().getMaxReds());
		}
		SnookerSharedPreferences.getInstance().saveActFrameId(activeFrameId);
	}
	
	public static Match getCurrentMatch() {
		if (match == null) {
			match = new Match();
		}
		return match;
	}
	
	public void newMatch(String fileName, List<Frame> frames, int player1FrameWins, int player2FrameWins) {
		
		Log.i(LOG_TAG, "newMatch() {");
		
		this.frames = frames;
		this.fileName = fileName;
		this.player1FrameWins = player1FrameWins;
		this.player2FrameWins = player2FrameWins;
		
		activeFrame = new Frame(frames.size() + 1, Settings.getInstance().getMaxReds());
		
		Log.i(LOG_TAG, " activeFrameId=" + activeFrame.getFrameId());
		startDate = Utils.parseStartDate(fileName);
		ssp.saveFileName(fileName);
		ssp.saveActFrameId(activeFrame.getFrameId());
	}
	
	public void newMatch() {
		fileName = null;
		frames = new LinkedList<Frame>();
		player1FrameWins = 0;
		player2FrameWins = 0;
		activeFrame = new Frame();
		startDate = new Date();
		ssp.clean();
		ssp.saveFileName(getFileName());
	}
	
	public String getPlayer1Name() {
		return player1Name;
	}

	public String getPlayer2Name() {
		return player2Name;
	}

	public void setPlayer1Name(String player1) {
		ssp.savePlayer1Name(player1);
		this.player1Name = player1;
	}

	public void setPlayer2Name(String player2) {
		ssp.savePlayer2Name(player2);
		this.player2Name = player2;
	}

	public void newFrame(boolean saveAct, int numberOfReds) {
		if (saveAct) {
			saveActFrame();
		}
		Frame newFrame = new Frame(frames.size() + 1, numberOfReds);
		activeFrame = newFrame;
		ssp.saveActFrameId(activeFrame.getFrameId());
	}
	
	public void saveActFrame() {
		if (activeFrame.getScoreHistory().getScoreList().size() > 0) {
			frames.add(activeFrame);
			calcFrameWins();
		}
	}
	
	public List<Frame> getFrames() {
		return frames;
	}
	
	public int getPlayer1FrameWins() {
		return player1FrameWins;
	}

	public int getPlayer2FrameWins() {
		return player2FrameWins;
	}

	public Frame getActFrame() {
		return activeFrame;
	}
	
	private void calcFrameWins() {
		int a = 0;
		int b = 0;
		for (Frame f: frames) {
			if (f.getPlayer1Score() > f.getPlayer2Score()) {
				a++;
			} else if (f.getPlayer1Score() < f.getPlayer2Score()) {
				b++;
			}
		}
		player1FrameWins = a;
		player2FrameWins = b;
	}
	
	public Date getStartDate() {
		return startDate;
	}
	
	public String getFileName() {
		if (fileName == null) {
			String timeStamp = Utils.getDateString(getStartDate());
			String name1 = getPlayer1Name().trim().replaceAll(" ", "_");
			String name2 = getPlayer2Name().trim().replaceAll(" ", "_");
			fileName = name1 + "-" + name2 + "_match_" + timeStamp + ".csv";
		}
		return fileName;
	}
	
	@Deprecated
	public void setPlayer1FrameWins(int player1FrameWins) {
		this.player1FrameWins = player1FrameWins;
	}

	@Deprecated
	public void setPlayer2FrameWins(int player2FrameWins) {
		this.player2FrameWins = player2FrameWins;
	}

	public void debug() {
		Log.i(LOG_TAG, "****************** Match **********************");
		if (fileName != null) {
			Log.i(LOG_TAG, "fileName=" + fileName);
		}
		Log.i(LOG_TAG, "****************** ActFrame **********************");
		activeFrame.debug();
		Log.i(LOG_TAG, "****************** History **********************");
		for (Frame f: frames) {
			f.debug();
		}
	}
}
